package com.ruoyi.shop.buying.service.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.concurrent.TimeUnit;

import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.redis.service.RedisService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import com.ruoyi.shop.buying.mapper.GroupBuyingMapper;
import com.ruoyi.shop.buying.domain.GroupBuying;
import com.ruoyi.shop.buying.service.IGroupBuyingService;
import com.alibaba.fastjson.JSON;

/**
 * 团购优惠Service业务层处理
 * 
 * @author ss
 * @date 2025-02-21
 */
@Slf4j
@Service
public class GroupBuyingServiceImpl implements IGroupBuyingService {

    private static final String GROUP_HASH_KEY = "group:hash";  // Hash存储所有团购数据
    private static final String CLICK_COUNT_KEY = "group:num:"; // 点击数计数器

    @Autowired
    private GroupBuyingMapper groupBuyingMapper;

    @Autowired
    private RedisService redisService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 查询团购优惠列表
     */
    @Override
    public List<GroupBuying> selectGroupBuyingList(GroupBuying groupBuying) {
        try {
            log.info("开始查询团购列表");

            // 从缓存获取
            Map<String, GroupBuying> cacheMap = redisService.getCacheMap(GROUP_HASH_KEY);
            List<GroupBuying> resultList;
            
            if (cacheMap != null && !cacheMap.isEmpty()) {
                log.info("从缓存获取团购列表");
                Collection<GroupBuying> values = cacheMap.values();
                // 过滤掉已删除的数据和已过期的数据
                resultList = values.stream()
                    .filter(item -> item.getDel() == 0 && item.getEndTime().after(new Date()))
                    .collect(Collectors.toList());
            } else {
                // 缓存未命中,查询数据库
                log.info("从数据库查询团购列表");
                if (groupBuying == null) {
                    groupBuying = new GroupBuying();
                }
                groupBuying.setDel(0);  // 只查询未删除的数据
                resultList = groupBuyingMapper.selectGroupBuyingList(groupBuying);

                // 更新缓存
                if (!CollectionUtils.isEmpty(resultList)) {
                    Map<String, Object> dataMap = new HashMap<>();
                    for (GroupBuying item : resultList) {
                        if (item.getEndTime().after(new Date())) {  // 只缓存未过期的数据
                            dataMap.put(String.valueOf(item.getId()), item);
                            // 为每个团购活动单独设置过期时间
                            long expireSeconds = (item.getEndTime().getTime() - System.currentTimeMillis()) / 1000;
                            if (expireSeconds > 0) {
                                String key = GROUP_HASH_KEY + ":" + item.getId();
                                redisService.setCacheObject(key, item, expireSeconds, TimeUnit.SECONDS);
                            }
                        }
                    }
                    if (!dataMap.isEmpty()) {
                        redisService.setCacheMap(GROUP_HASH_KEY, dataMap);
                    }
                }
            }

            // 实时获取点击数
            if (!CollectionUtils.isEmpty(resultList)) {
                for (GroupBuying item : resultList) {
                    String numKey = CLICK_COUNT_KEY + item.getId();
                    String numStr = stringRedisTemplate.opsForValue().get(numKey);
                    if (numStr != null) {
                        item.setNum(Long.parseLong(numStr));
                    }
                }
            }

            return resultList;

        } catch (Exception e) {
            log.error("查询团购列表异常", e);
            throw e;
        }
    }

    /**
     * 查询单个团购详情
     */
    @Override
    public GroupBuying selectGroupBuyingById(Long id) {
        try {
            log.info("开始查询团购详情, id: {}", id);
            
            // 从Hash中获取数据
            GroupBuying groupBuying = redisService.getCacheMapValue(GROUP_HASH_KEY, String.valueOf(id));
            log.info("从缓存获取团购数据: {}", groupBuying);
            
            if (groupBuying == null) {
                // 从数据库查询
                log.info("缓存未命中，从数据库查询, id: {}", id);
                groupBuying = groupBuyingMapper.selectGroupBuyingById(id);
                if (groupBuying != null && groupBuying.getDel() == 0) {
                    // 检查是否过期
                    if (groupBuying.getEndTime().after(new Date())) {
                        // 存入Hash并设置过期时间
                        redisService.setCacheMapValue(GROUP_HASH_KEY, String.valueOf(id), groupBuying);
                        // 计算过期时间
                        long expireSeconds = (groupBuying.getEndTime().getTime() - System.currentTimeMillis()) / 1000;
                        if (expireSeconds > 0) {
                            String key = GROUP_HASH_KEY + ":" + id;
                            redisService.setCacheObject(key, groupBuying, expireSeconds, TimeUnit.SECONDS);
                        }
                        log.info("数据库查询结果已存入缓存，过期时间: {}秒", expireSeconds);
                    }
                }
            }
            
            if (groupBuying != null && groupBuying.getDel() == 0 && groupBuying.getEndTime().after(new Date())) {
                // 更新点击数
                String numKey = CLICK_COUNT_KEY + id;
                // 先获取当前点击数
                String numStr = stringRedisTemplate.opsForValue().get(numKey);
                Long currentNum = numStr != null ? Long.parseLong(numStr) : 0L;
                // 增加点击数
                Long newNum = stringRedisTemplate.opsForValue().increment(numKey);
                log.info("团购ID: {} 的点击数从 {} 增加到 {}", id, currentNum, newNum);
                groupBuying.setNum(newNum);
            } else {
                log.warn("未找到团购数据或数据已删除或已过期, id: {}", id);
                return null;
            }
            
            return groupBuying;
        } catch (Exception e) {
            log.error("查询团购详情异常", e);
            throw e;
        }
    }

    /**
     * 新增团购优惠
     */
    @Override
    public int insertGroupBuying(GroupBuying groupBuying) {
        try {
            log.info("开始新增团购优惠, 参数: {}", groupBuying);
            // 设置初始点击数和删除标志
            groupBuying.setNum(0L);
            groupBuying.setDel(0);
            
            // 先执行数据库插入
            int rows = groupBuyingMapper.insertGroupBuying(groupBuying);
            log.info("数据库插入结果: {}, 返回的ID: {}", rows, groupBuying.getId());
            
            if (rows > 0 && groupBuying.getId() != null) {
                try {
                    // 从数据库查询最新数据
                    GroupBuying latestData = groupBuyingMapper.selectGroupBuyingById(groupBuying.getId());
                    if (latestData != null) {
                        // 更新缓存
                        Map<String, Object> dataMap = new HashMap<>();
                        dataMap.put(String.valueOf(latestData.getId()), latestData);
                        redisService.setCacheMap(GROUP_HASH_KEY, dataMap);
                        log.info("缓存更新成功，使用最新数据，团购ID: {}", latestData.getId());
                    }
                } catch (Exception e) {
                    log.error("缓存更新失败，但数据库插入成功，团购ID: {}", groupBuying.getId(), e);
                    // 缓存更新失败不影响数据库插入的结果
                }
            } else {
                log.error("数据库插入失败或未获取到ID");
            }
            
            return rows;
        } catch (Exception e) {
            log.error("新增团购优惠异常", e);
            throw e;
        }
    }

    /**
     * 删除团购优惠
     */
    @Override
    public int deleteGroupBuyingByIds(Long[] ids) {
        try {
            log.info("开始删除团购优惠，ids: {}", Arrays.toString(ids));
            int rows = groupBuyingMapper.deleteGroupBuyingByIds(ids);
            if (rows > 0) {
                // 从缓存中删除
                for (Long id : ids) {
                    redisService.deleteCacheMapValue(GROUP_HASH_KEY, String.valueOf(id));
                }
            }
            return rows;
        } catch (Exception e) {
            log.error("删除团购优惠异常", e);
            throw e;
        }
    }

    /**
     * 删除单个团购优惠
     */
    @Override
    public int deleteGroupBuyingById(Long id) {
        try {
            log.info("开始删除团购优惠，id: {}", id);
            int rows = groupBuyingMapper.deleteGroupBuyingById(id);
            if (rows > 0) {
                // 从缓存中删除
                redisService.deleteCacheMapValue(GROUP_HASH_KEY, String.valueOf(id));
            }
            return rows;
        } catch (Exception e) {
            log.error("删除团购优惠异常", e);
            throw e;
        }
    }

    /**
     * 修改团购优惠
     */
    @Override
    public int updateGroupBuying(GroupBuying groupBuying) {
        try {
            log.info("开始修改团购优惠，id: {}", groupBuying.getId());
            int rows = groupBuyingMapper.updateGroupBuying(groupBuying);
            if (rows > 0) {
                // 更新缓存
                redisService.setCacheMapValue(GROUP_HASH_KEY, 
                    String.valueOf(groupBuying.getId()), groupBuying);
            }
            return rows;
        } catch (Exception e) {
            log.error("修改团购优惠异常", e);
            throw e;
        }
    }

    /**
     * 同步点击数到数据库
     */
    public void syncClickCountToDb() {
        try {
            log.info("开始同步点击数到数据库");
            
            // 获取所有团购数据的点击数
            Set<String> keys = stringRedisTemplate.keys(CLICK_COUNT_KEY + "*");
            if (keys == null || keys.isEmpty()) {
                log.info("没有需要同步的点击数数据");
                return;
            }

            log.info("需要同步的点击数key列表: {}", keys);
            
            // 批量更新数据库
            for (String key : keys) {
                try {
                    // 从key中提取ID
                    String idStr = key.substring(CLICK_COUNT_KEY.length());
                    if (StringUtils.isEmpty(idStr)) {
                        log.warn("跳过无效的key: {}", key);
                        continue;
                    }
                    
                    Long id = Long.parseLong(idStr);
                    
                    // 获取Redis中的点击数
                    String numStr = stringRedisTemplate.opsForValue().get(key);
                    if (numStr != null) {
                        Long num = Long.parseLong(numStr);
                        
                        log.info("同步团购ID: {} 的点击数: {}", id, num);
                        
                        // 更新数据库
                        GroupBuying groupBuying = new GroupBuying();
                        groupBuying.setId(id);
                        groupBuying.setNum(num);
                        
                        int rows = groupBuyingMapper.updateGroupBuying(groupBuying);
                        log.info("更新团购ID: {} 的点击数结果: {}", id, rows > 0 ? "成功" : "失败");
                    }
                } catch (NumberFormatException e) {
                    log.error("无效的数字格式, key: {}", key);
                    // 可以考虑在这里删除无效的key
                    stringRedisTemplate.delete(key);
                } catch (Exception e) {
                    log.error("同步点击数异常, key: {}", key, e);
                }
            }
            
            log.info("点击数同步完成");
            
        } catch (Exception e) {
            log.error("同步点击数到数据库异常", e);
            throw e;
        }
    }
}
